package com.lumeng.spring.orm.utils;

import com.lumeng.spring.orm.Condition;
import com.lumeng.spring.orm.ConditionFactory;
import com.lumeng.spring.orm.Order;
import com.lumeng.spring.orm.domain.Domain;
import com.lumeng.spring.orm.hibernate.JpaCondition;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.BindingResult;

import javax.persistence.Transient;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

public class ConditionUtils {
	public static Collection<Condition> getConditions(String prefix, Domain bean, BindingResult result,
													  Map<String, String> filterMap, Map<String, String[]> parameterMap) {
		Collection conditions = new ArrayList();
		if (prefix != null) {
			prefix = prefix + ".";
		} else {
			prefix = "";
		}
		PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(bean.getClass());
		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			String name = propertyDescriptor.getName();
			if ("class".equals(name)) {
				continue;
			}
			String propertyName = prefix + name;

			Transient tsi = (Transient) propertyDescriptor.getReadMethod().getAnnotation(Transient.class);
			if (tsi != null) {
				continue;
			}
			Object value = result.getFieldValue(propertyName);
			String operator = (String) filterMap.get(propertyName);
			if (operator == null) {
				operator = "EQUALS";
			}
			if ((value != null) && (!value.equals(""))) {
				if ((value instanceof Domain)) {
					conditions.addAll(getConditions(propertyName, (Domain) value, result, filterMap, parameterMap));
				} else {
					if ((value instanceof Set)) {
						continue;
					}
					if ((value instanceof Collection)) {
						continue;
					}
					if ((value instanceof Map)) {
						for (Map.Entry entry : parameterMap.entrySet()) {
							if ((((String) entry.getKey()).startsWith(prefix + propertyName + "."))
									&& (((String[]) entry.getValue()).length > 0)) {
								conditions.add(ConditionFactory.getInstance().getCondition((String) entry.getKey(),
										operator, ((String[]) entry.getValue())[0]));
							}
						}
					} else {
						if (!parameterMap.containsKey(propertyName)) {
							continue;
						}
						conditions.add(ConditionFactory.getInstance().getCondition(propertyName, operator, value));
					}
				}
			}
		}
		return conditions;
	}

	public static Condition getCondition(String propertyName, String operator, Object value) {
		return new JpaCondition(propertyName, operator, value);
	}

	public static Order getOrder(String propertyName, boolean ascending) {
		return new Order(propertyName, ascending);
	}

}